# coding=utf-8
import re
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import ModelSerializer
from erp_system.models import UserModel  # 因为有导包路径，所以直接导App下的model就行了
from MSB_ERP.apps.erp_system.serializer.role_serializer import BaseRolesSerializer
from MSB_ERP.apps.erp_system.serializer.dept_serializer import DeptSerializer
from rest_framework import serializers

class UserRegisterSerializer(ModelSerializer):
    '''
    用户注册的序列化类
    '''

    class Meta:
        model = UserModel
        # 指定显示出去的字段（返回到浏览器的数据）
        fields = ('id', 'username', 'password', 'phone', 'real_name',)

        # 校验器，他自带的数据库字段中做校验
        extra_kwargs = {
            'username': {
                'max_length': 12,
                'min_length': 2
            },
            'password': {
                'max_length': 8,
                'min_length': 6,
                # 意思是只写，只是通过反序列化的时候用一下，其他时候都会不用的
                'write_only': True
            }
        }

    ''' 这个是自己添加的属性才需要这样验证的 '''

    # 这个是这样的的校验器：validate_需要定义的属性（传要定义的属性）
    def validate_phone(self, phone):
        '''
        验证手机号码，是一个验证的函数
        '''
        if not phone:
            return phone
        else:
            # 如果验证没有通过的话，就报错
            if not re.match(r'^1[13589]\d{9}$', phone):
                raise ValidationError('请输入正确的手机号码')
        return phone

    def create(self, validated_data):
        '''必须重写Create，因为用户密码是不能直接插入数据库的'''
        # **validated_data是做解包的意思，可以直接插入数据库中的
        user = UserModel.objects.create_user(**validated_data)
        return user


class UserUpdateOrDeleteSerializer(ModelSerializer):
    '''
    只用于：修改和删除，修改包括：id，phone，real_name，role_id，dept_id
    '''

    class Meta:
        model = UserModel
        fields = ('id', 'phone', 'real_name', 'roles', 'dept')


class UserGetSerializer(ModelSerializer):
    '''
    只用于查询用户，返回id，username，phone，real_name，roles，dept，角色的详细信息，用户所在部门的详细信息
    '''
    roles = BaseRolesSerializer(many=True, read_only=True)  # 新增返回出去的数据
    dept = DeptSerializer(many=False, read_only=True)

    class Meta:
        model = UserModel
        fields = ('id', 'username', 'phone', 'real_name', 'roles', 'dept')  # 指定发出去的数据是什么


class ResetPasswordSerializer(ModelSerializer):
    '''
    只用于：修改密码，包含三个参数：原密码，新密码，新密码确认
    '''
    # 定义多两个字段
    new_password = serializers.CharField(required=True,write_only=True)
    confirm_password = serializers.CharField(required=True,write_only=True)

    class Meta:
        model = UserModel
        # password和confirm_password只用于反序列化
        fields = ('id', 'password', 'new_password', 'confirm_password')

        # 当修改完密码之后不能把密码返回出去
        extra_kwargs = {
            'password': {'write_only': True},
            'new_password': {'write_only': True},
            'confirm_password': {'write_only': True}
        }

    def validate(self, attrs):
        '''表单参数的验证，确认新密码和新密码是否相同'''
        password = attrs.get('password')  # 原密码
        new_password = attrs.get('new_password')  # 新密码
        confirm_password = attrs.get('confirm_password')  # 确认密码

        if not password:
            # raise ValidationError表示抛出异常
            raise ValidationError('字段password为必填项')
        if not new_password:
            # raise ValidationError表示抛出异常
            raise ValidationError('字段new_password为必填项')
        if not confirm_password:
            # raise ValidationError表示抛出异常
            raise ValidationError('字段confirm_password为必填项')
        if confirm_password != new_password:
            raise ValidationError('两次密码不一致')
        return attrs  # 如果都没有报错的话，就返回当前的attrs

    def save(self, **kwargs):  # 不重写函数的话，他会把密码直接以明文的存入数据库的
        # 必须重写save函数，否则会以明文的方式保存到数据库中

        # instance是父类提供的
        # instance.check_password比对一下密码是否正确
        # self.validated_data.get('password')数据在验证之后数据里面（原始密码）
        if not self.instance.check_password(self.validated_data.get('password')):
            raise ValidationError('原始密码错误，请重新输入原始密码')

        # 当你在DRF中使用序列化器时，调用 is_valid() 方法后，序列化器会对传入的数据进行验证。
        # 如果验证通过，验证后的数据会存储在 validated_data 中。
        self.instance.set_password(self.validated_data.get('new_password')) # 插入新数据也就是密文的密码
        self.instance.save()
        return self.instance
